package com.mx.tool.intentionAction.impl;

import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.util.IncorrectOperationException;
import com.mx.tool.intentionAction.IAction;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

/**
 * @Author: mengxiang.
 * @create: 2021-03-08 10:06
 * @Description:
 */
public class SetterAction extends PsiElementBaseIntentionAction implements IAction {


    @Nls
    @NotNull
    @Override
    public String getFamilyName() {
        return "生成set方法";
    }

    @Nls
    @NotNull
    @Override
    public String getText() {
        return "生成set方法";
    }

    @Override
    public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
        PsiElement psiParent = PsiTreeUtil.getParentOfType(element,
                PsiLocalVariable.class, PsiMethod.class);
        if (psiParent == null) {
            return;
        }
        if (psiParent instanceof PsiLocalVariable) {
            PsiLocalVariable psiLocal = (PsiLocalVariable) psiParent;
            if (!(psiLocal.getParent() instanceof PsiDeclarationStatement)) {
                return;
            }
            PsiElement parent = psiLocal.getParent();
            PsiClass psiClass = PsiTypesUtil.getPsiClass(psiLocal.getType());
            if (psiClass == null) {
                return;
            }
            PsiField[] psiFields = psiClass.getFields();
            if (psiFields.length > 0) {
                String generateName = psiLocal.getName();
                StringBuilder methodBuilder = new StringBuilder();
                PsiDocumentManager psiDocumentManager = PsiDocumentManager
                        .getInstance(project);
                Document document = psiDocumentManager
                        .getDocument(element.getContainingFile());
                if (document == null) {
                    return;
                }
                methodBuilder
                        .append("\n")
                        .append(calOff(document, parent.getTextOffset()))
                        .append(psiClass.getName())
                        .append(" ")
                        .append(StringUtils.uncapitalize(psiClass.getName()))
                        .append(" ")
                        .append("=")
                        .append(" ")
                        .append("new")
                        .append(" ")
                        .append(psiClass.getName())
                        .append("();");
                for (PsiField psiField : psiFields) {
                    if (!excludeFieldLists.contains(psiField.getName())) {
                        String fieldName = psiField.getName();
                        methodBuilder
                                .append("\n")
                                .append(calOff(document, parent.getTextOffset()))
                                .append(generateName)
                                .append(".set")
                                .append(StringUtils.capitalize(fieldName));
                        methodBuilder.append("(");
                        String fieldTypeText = psiField.getType().getCanonicalText();
                        if (psiField.getName().equals("id") && "java.lang.String".equals(fieldTypeText)) {
                            methodBuilder.append("IdUtil.fastSimpleUUID()");
                        } else if (datetimeFields.contains(fieldName) && "java.lang.Long".equals(fieldTypeText)) {
                            methodBuilder.append("System.currentTimeMillis()");
                        } else if (datetimeFields.contains(fieldName) && "java.sql.Timestamp".equals(fieldTypeText)) {
                            methodBuilder.append("new Timestamp(System.currentTimeMillis())");
                        } else if (usersFields.contains(fieldName)) {
                            methodBuilder.append("saUtil.loginId()");
                        } else {
                            methodBuilder.append(fieldType.get(fieldTypeText));
                        }
                        methodBuilder.append(");");
                    }
                }
                document.insertString(parent.getTextOffset() + parent.getText().length(),
                        methodBuilder.toString());
                psiDocumentManager.doPostponedOperationsAndUnblockDocument(document);
                psiDocumentManager.commitDocument(document);
                FileDocumentManager.getInstance().saveDocument(document);
            }
        }
    }

    @NotNull
    private static String calOff(Document document, int statementOffset) {
        String splitText = "";
        int cur = statementOffset;
        String text = document.getText(new TextRange(cur - 1, cur));
        while (text.equals(" ") || text.equals("\t")) {
            splitText = text + splitText;
            cur--;
            if (cur < 1) {
                break;
            }
            text = document.getText(new TextRange(cur - 1, cur));
        }
        return splitText;
    }

    @Override
    public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
        return true;
    }
}
